iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 24
1
Mobile Development

新手試試用Flutter做Netflix UI系列 第 24

[Day24]Flutter Netflix UI 不讓底部導航欄消失,嘗試用Navigator 2.0

  • 分享至 

  • xImage
  •  

大家好,今天更新了Flutter到1.22.1,它就發生錯誤了,主要是之前使用的custom_navigator package有些問題,剛好發佈了新的Navigator 2.0 API就來試試吧!

這篇我是按照Learning Flutter’s new navigation and routing system裡面的程式做的

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 1.22.1, on Mac OS X 10.15.6 19G2021, locale zh-Hant-TW)
 
[!] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
    ! Some Android licenses not accepted.  To resolve this, run: flutter doctor --android-licenses
[✓] Xcode - develop for iOS and macOS (Xcode 12.0)
[✓] Android Studio (version 4.0)
[✓] Connected device (2 available)

先前說過不想讓底部導航欄消失,是因為我們跳轉頁面的時候使用的Navigator.of(context).push(),是去尋找最靠近的Navigator然後跳轉頁面,這時候因為只有MaterialApp裡面有一個Navigator所以造成底部導航欄被擋住,因此要新建一個Navigator去避免這個狀況。

//這是做底部導航欄那篇,原本此處使用CustomNavigator,改為直接用pages[currentIndex]
Scaffold(
      body:pages[currentIndex],
      bottomNavigationBar: BottomNavigationBar()

pages裡面放等下要建的Navigator

  List<Widget> pages = [
    HomeNavigator(),
    SearchingPage(),
    ComingSoonPage(),
    SearchingPage(),
    MorePage(),
  ];

先建一個名為HomeNavigator的StatefulWidget,return Navigator

  return Navigator(
      pages: [
        MaterialPage(
            key: ValueKey('HomePage'),
            child: HomePage(
            )),
      ],)

這時候在HomePage裡面點擊劇集跳轉到詳細頁面的時候使用Navigator.of(context).push()底部導航欄就不會消失了

                    onTap: () {
                      Navigator.of(context).push(MaterialPageRoute(
                          builder: (BuildContext context) =>
                              SeriesDetailPage()));
                    },

Navigator 2.0

今天我想更進一步試試看新功能,不使用push
先命一個變數來判斷pages裡面是否要出現SeriesDetailPage,點擊事件會傳到HomePage裡面

  Series _selectedSeries;
  
  _handleSeriesTapped(Series series) {
    _selectedSeries = series;
    setState(() {});
  }

使用collection if判斷是否增加第二個頁面

pages: [
        MaterialPage(
            key: ValueKey('HomePage'),
            child: HomePage(
              onTapped: _handleSeriesTapped,
            )),
        if (_selectedSeries != null) //如果有點擊某個劇集這裡面就加上這頁
          MaterialPage(
              key: ValueKey(_selectedSeries),
              child: SeriesDetailPage(series: _selectedSeries))
      ],

原先的HomePage加上onTapped,待劇集被點擊的時候呼叫

class HomePage extends StatefulWidget {
  ValueChanged<Series> onTapped;
  
  HomePage({this.onTapped});

  @override
  _HomePageState createState() => _HomePageState();
}

page不為null的時候onPopPage也不能為null,要記得Navigator裡面加上onPopPage,不然會報錯。

 onPopPage: (route, result) {
        if (!route.didPop(result)) {
        //返回失敗
          return false;
        }
        // Update the list of pages by setting _selectedBook to null
        setState(() {
          _selectedSeries = null; //如果返回成功把它變null再setState
        });
        return true;
      },

以下是HomeNavigator目前使用pages的完整程式

class HomeNavigator extends StatefulWidget {
  @override
  _HomeNavigatorState createState() => _HomeNavigatorState();
}

class _HomeNavigatorState extends State<HomeNavigator> {
  Series _selectedSeries;

  @override
  Widget build(BuildContext context) {
    //Navigator的构造函数中有一个pages参数。如果列表中的Page发生变化,Navigator就会更新堆栈的路由来匹配。
    return Navigator(
      pages: [
        MaterialPage(
            key: ValueKey('HomePage'),
            child: HomePage(
              onTapped: _handleSeriesTapped,
            )),
        if (_selectedSeries != null)
          MaterialPage(
              key: ValueKey(_selectedSeries),
              child: SeriesDetailPage(series: _selectedSeries))
      ],
      onPopPage: (route, result) {
        print("route: $route result: $result");
        if (!route.didPop(result)) {
          return false;
        }

        // Update the list of pages by setting _selectedSeries to null
        setState(() {
          _selectedSeries = null;
        });
        return true;
      },
    );
  }

  _handleSeriesTapped(Series series) {
    _selectedSeries = series;
    setState(() {});
  }
}

附上今天的效果圖
Day24

這次更新還有一大部分是跟Router有關,我目前還沒有找到太多相關的資料,這個資料的來源是做一個網頁的例子,也還沒找到有什麼其他例子可以學習。

GitHub連結: flutter-netflix-clone


上一篇
[Day23]Flutter Netflix UI 使用Shimmer為首頁加個微光閃爍的載入畫面
下一篇
[Day25] Flutter Netflix UI Internationalization國際化
系列文
新手試試用Flutter做Netflix UI30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言